package com.open.tool;

import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.geometry.Bounds;
import javafx.geometry.Rectangle2D;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Screen;
import javafx.stage.Stage;

/**
 * 图片查看器控制器类
 * 提供图片显示、放大镜功能、坐标显示和矩形绘制功能
 */
public class ImageViewerController {
    // FXML注入的UI组件
    @FXML private ImageView imageView;           // 主图片显示组件
    @FXML private StackPane magnifierPane;      // 放大镜容器
    @FXML private ImageView magnifierView;      // 放大镜中的图片显示
    @FXML private Label statusLabel;            // 状态标签，显示图片信息和坐标
    @FXML private ScrollPane scrollPane;        // 滚动面板
    @FXML private StackPane imageContainer;     // 图片容器
    @FXML private VBox mainContainer;           // 主容器
    @FXML private TextField x1Field, y1Field, x2Field, y2Field; // 坐标输入框
    @FXML private Button drawButton;            // 绘制按钮
    @FXML private Canvas coordinateCanvas;      // 用于绘制坐标矩形的画布

    // 私有成员变量
    private Circle redDot;                      // 放大镜中心的红点
    private Image originalImage;                // 原始图片对象
    private Runnable onCloseCallback;           // 窗口关闭回调函数
    private GraphicsContext gc;                 // 画布的图形上下文

    // 常量定义
    private static final int MAGNIFIER_SIZE = 150;              // 放大镜尺寸
    private static final int ZOOM_FACTOR = 20;                  // 放大倍数
    private static final int RED_DOT_RADIUS = 2;               // 红点半径
    private static final int MAGNIFIER_HORIZONTAL_OFFSET = 50;  // 放大镜水平偏移量

    /**
     * FXML初始化方法，在FXML加载完成后自动调用
     */
    @FXML
    public void initialize() {
        // 创建放大镜中心的红点
        redDot = new Circle(RED_DOT_RADIUS, Color.RED);
        magnifierPane.getChildren().add(redDot);

        // 初始化放大镜设置
        magnifierPane.setVisible(false);                        // 默认隐藏放大镜
        magnifierPane.setPrefSize(MAGNIFIER_SIZE, MAGNIFIER_SIZE);
        magnifierView.setFitWidth(MAGNIFIER_SIZE);
        magnifierView.setFitHeight(MAGNIFIER_SIZE);

        // 设置UI组件样式
        mainContainer.setStyle("-fx-background-color: #f0f0f0;");
        statusLabel.setStyle("-fx-background-color: #e0e0e0; -fx-padding: 5px;");
        scrollPane.setStyle("-fx-background-color: transparent;");
        magnifierPane.setStyle("-fx-background-color: white; -fx-border-color: black; -fx-border-width: 2px;");

        // 初始化画布和图形上下文
        gc = coordinateCanvas.getGraphicsContext2D();
        // 绑定画布尺寸到图片容器尺寸
        coordinateCanvas.widthProperty().bind(imageContainer.widthProperty());
        coordinateCanvas.heightProperty().bind(imageContainer.heightProperty());
        coordinateCanvas.toFront();                             // 将画布置于最前层
        coordinateCanvas.setMouseTransparent(true);             // 设置画布不响应鼠标事件

        // 绑定绘制按钮事件
        drawButton.setOnAction(e -> drawSelection());

        // 在JavaFX线程中设置窗口关闭事件
        Platform.runLater(() -> {
            Stage stage = (Stage) imageView.getScene().getWindow();
            stage.setOnCloseRequest(event -> {
                if (onCloseCallback != null) {
                    onCloseCallback.run();                      // 执行关闭回调
                }
            });
        });
    }

    /**
     * 设置窗口关闭回调函数
     * @param callback 回调函数
     */
    public void setOnCloseCallback(Runnable callback) {
        this.onCloseCallback = callback;
    }

    /**
     * 加载图片
     * @param url 图片URL或路径
     */
    public void loadImage(String url) {
        // 创建图片对象并设置到ImageView
        originalImage = new Image(url);
        imageView.setImage(originalImage);
        imageView.setPreserveRatio(true);                       // 保持图片宽高比

        // 设置图片容器尺寸为原始图片尺寸
        imageContainer.setPrefSize(originalImage.getWidth(), originalImage.getHeight());

        // 在JavaFX线程中执行UI更新操作
        Platform.runLater(() -> {
            adjustWindowSize();                                 // 调整窗口尺寸

            // 设置画布尺寸并清空内容
            coordinateCanvas.widthProperty().unbind();
            coordinateCanvas.setWidth(imageContainer.getWidth());
            coordinateCanvas.heightProperty().unbind();
            coordinateCanvas.setHeight(imageContainer.getHeight());
            gc.clearRect(0, 0, coordinateCanvas.getWidth(), coordinateCanvas.getHeight());
        });

        updateStatusLabel();                                    // 更新状态标签
        setupMouseTracking();                                   // 设置鼠标跟踪

        // 清空坐标输入框
        x1Field.clear();
        y1Field.clear();
        x2Field.clear();
        y2Field.clear();
    }

    /**
     * 调整窗口尺寸以适应图片
     */
    private void adjustWindowSize() {
        Stage stage = (Stage) imageView.getScene().getWindow();
        Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds(); // 获取屏幕可视区域

        // 计算新的窗口尺寸，不超过屏幕的90%
        double newWidth = Math.min(originalImage.getWidth() + 40, screenBounds.getWidth() * 0.9);
        double newHeight = Math.min(originalImage.getHeight() + 150, screenBounds.getHeight() * 0.9);

        // 设置窗口尺寸并居中显示
        stage.setWidth(newWidth);
        stage.setHeight(newHeight);
        stage.centerOnScreen();
    }

    /**
     * 设置鼠标移动跟踪
     */
    private void setupMouseTracking() {
        scrollPane.setOnMouseMoved(event -> {
            // 获取鼠标在滚动面板中的坐标
            double x = event.getX();
            double y = event.getY();

            // 将显示坐标转换为原始图片坐标
            int originalX = (int) (x * originalImage.getWidth() / imageContainer.getWidth());
            int originalY = (int) (y * originalImage.getHeight() / imageContainer.getHeight());

            updateStatusLabel(originalX, originalY);            // 更新状态标签显示坐标
            updateMagnifier(x, y);                             // 更新放大镜
        });
    }

    /**
     * 更新状态标签显示图片信息和当前坐标
     * @param x X坐标
     * @param y Y坐标
     */
    private void updateStatusLabel(int x, int y) {
        statusLabel.setText(String.format("图片尺寸: %.0fx%.0f | 坐标: (%d, %d)",
                originalImage.getWidth(), originalImage.getHeight(), x, y));
    }

    /**
     * 更新状态标签仅显示图片信息
     */
    private void updateStatusLabel() {
        statusLabel.setText(String.format("图片尺寸: %.0fx%.0f",
                originalImage.getWidth(), originalImage.getHeight()));
    }

    /**
     * 更新放大镜显示
     * @param x 鼠标X坐标
     * @param y 鼠标Y坐标
     */
    private void updateMagnifier(double x, double y) {
        if (originalImage == null) return;                      // 如果没有图片则返回

        // 获取图片容器的显示尺寸
        double imageWidth = imageContainer.getWidth();
        double imageHeight = imageContainer.getHeight();

        // 将显示坐标转换为原始图片坐标
        int imageX = (int) (x * originalImage.getWidth() / imageWidth);
        int imageY = (int) (y * originalImage.getHeight() / imageHeight);

        // 计算放大镜显示区域
        int halfSize = MAGNIFIER_SIZE / (2 * ZOOM_FACTOR);      // 放大镜显示区域的一半尺寸
        PixelReader reader = originalImage.getPixelReader();    // 获取原图像素读取器
        WritableImage magnifiedImage = new WritableImage(MAGNIFIER_SIZE, MAGNIFIER_SIZE); // 创建放大后的图片

        // 生成放大后的图片像素
        for (int i = 0; i < MAGNIFIER_SIZE; i++) {
            for (int j = 0; j < MAGNIFIER_SIZE; j++) {
                // 计算对应的原图坐标
                int sourceX = imageX - halfSize + i / ZOOM_FACTOR;
                int sourceY = imageY - halfSize + j / ZOOM_FACTOR;

                // 检查坐标是否在原图范围内
                if (sourceX >= 0 && sourceX < originalImage.getWidth() &&
                    sourceY >= 0 && sourceY < originalImage.getHeight()) {
                    // 复制像素到放大图片
                    magnifiedImage.getPixelWriter().setArgb(i, j, reader.getArgb(sourceX, sourceY));
                }
            }
        }

        magnifierView.setImage(magnifiedImage);                 // 设置放大镜图片

        // 获取视口边界
        Bounds viewportBounds = scrollPane.getViewportBounds();
        double viewportWidth = viewportBounds.getWidth();
        double viewportHeight = viewportBounds.getHeight();

        // 智能计算放大镜位置，避免遮挡鼠标区域
        double magnifierX, magnifierY;

        // 水平位置决策：优先放在右侧，如果空间不够则放左侧
        if (x + MAGNIFIER_HORIZONTAL_OFFSET + MAGNIFIER_SIZE <= viewportWidth) {
            // 右侧有足够空间，放在鼠标右侧
            magnifierX = x + MAGNIFIER_HORIZONTAL_OFFSET;
        } else if (x - MAGNIFIER_HORIZONTAL_OFFSET - MAGNIFIER_SIZE >= 0) {
            // 右侧空间不够，放在鼠标左侧
            magnifierX = x - MAGNIFIER_HORIZONTAL_OFFSET - MAGNIFIER_SIZE;
        } else {
            // 左右都没有足够空间，放在视口边缘
            magnifierX = Math.max(0, Math.min(x - MAGNIFIER_SIZE / 2, viewportWidth - MAGNIFIER_SIZE));
        }

        // 垂直位置决策：优先居中，然后考虑上下空间
        if (y - MAGNIFIER_SIZE / 2 >= 0 && y + MAGNIFIER_SIZE / 2 <= viewportHeight) {
            // 垂直居中有足够空间
            magnifierY = y - MAGNIFIER_SIZE / 2;
        } else if (y + MAGNIFIER_SIZE <= viewportHeight) {
            // 上方空间不够，放在鼠标下方
            magnifierY = y;
        } else if (y - MAGNIFIER_SIZE >= 0) {
            // 下方空间不够，放在鼠标上方
            magnifierY = y - MAGNIFIER_SIZE;
        } else {
            // 上下都没有足够空间，放在视口边缘
            magnifierY = Math.max(0, Math.min(y - MAGNIFIER_SIZE / 2, viewportHeight - MAGNIFIER_SIZE));
        }

        // 最终边界检查，确保放大镜完全在视口内
        magnifierX = Math.max(0, Math.min(magnifierX, viewportWidth - MAGNIFIER_SIZE));
        magnifierY = Math.max(0, Math.min(magnifierY, viewportHeight - MAGNIFIER_SIZE));

        // 设置放大镜位置
        magnifierPane.setLayoutX(magnifierX);
        magnifierPane.setLayoutY(magnifierY);

        // 设置红点位置在放大镜中心
        redDot.setLayoutX(MAGNIFIER_SIZE / 2);
        redDot.setLayoutY(MAGNIFIER_SIZE / 2);

        // 只有当鼠标在视口内时才显示放大镜
        boolean isInViewport = x >= 0 && x <= viewportWidth && y >= 0 && y <= viewportHeight;
        magnifierPane.setVisible(isInViewport);
    }

    /**
     * 根据输入的坐标绘制选择矩形
     */
    private void drawSelection() {
        System.out.println("drawSelection method called");      // 调试输出

        // 检查图形上下文和画布是否可用
        if (gc == null) {
            System.out.println("GraphicsContext is null");
            return;
        }
        if (coordinateCanvas == null) {
            System.out.println("Canvas is null");
            return;
        }

        // 清除之前绘制的所有内容
        gc.clearRect(0, 0, coordinateCanvas.getWidth(), coordinateCanvas.getHeight());

        try {
            // 解析输入的坐标值
            double x1 = Double.parseDouble(x1Field.getText());
            double y1 = Double.parseDouble(y1Field.getText());
            double x2 = Double.parseDouble(x2Field.getText());
            double y2 = Double.parseDouble(y2Field.getText());

            // 限制坐标在图片范围内
            x1 = Math.max(0, Math.min(x1, originalImage.getWidth()));
            y1 = Math.max(0, Math.min(y1, originalImage.getHeight()));
            x2 = Math.max(0, Math.min(x2, originalImage.getWidth()));
            y2 = Math.max(0, Math.min(y2, originalImage.getHeight()));

            // 计算矩形参数（确保宽高为正值）
            double rectX = Math.min(x1, x2);                    // 矩形左上角X坐标
            double rectY = Math.min(y1, y2);                    // 矩形左上角Y坐标
            double rectWidth = Math.abs(x2 - x1);               // 矩形宽度
            double rectHeight = Math.abs(y2 - y1);              // 矩形高度

            // 确保画布在最前层并可见
            coordinateCanvas.toFront();
            coordinateCanvas.setOpacity(1.0);
            coordinateCanvas.setVisible(true);

            // 设置绘制样式并绘制矩形
            gc.setStroke(Color.RED);                            // 设置边框颜色为红色
            gc.strokeRect(rectX, rectY, rectWidth, rectHeight); // 绘制矩形边框

        } catch (NumberFormatException e) {
            // 处理坐标输入格式错误
            System.out.println("Invalid coordinate input: " + e.getMessage());
            Alert alert = new Alert(Alert.AlertType.ERROR, "请输入有效的坐标值");
            alert.showAndWait();
        }
    }
}
